feat(wardroom): refuse an impossible brief before the spawn burns a run - #10
Merged
Merged
Conversation
Three briefs written on 2026-08-28/29 specified work no crewmate could do - moving a gitignored file, fixing briefs under gitignored data/, and "testing" a pool-leasing command under FM_HOME=$(mktemp -d), which leaks a durable lease into the captain's live pool. The intake council caught all three, but only after a full cycle of three model lenses. A fourth reached a live crewmate: a brief carrying the retired >> status redirect, whose reports the permission profile silently refused for ten minutes while the pane looked idle. All four are structural - decidable from the brief text, the project's own ignore rules, and a list of known-hazardous commands, with no model in the loop. bin/fm-preflight-lib.sh decides them, and bin/fm-spawn.sh consults it after the brief-exists check and ahead of the council: nothing is created before the refusal, and scouts are covered where the council exempts them. Secondmates are exempt - their home is a firstmate home, where data/ and state/ are theirs to operate. The refusal names the offending path or command and says why; one that only said "invalid brief" would cost another cycle to diagnose, which is half of what this saves. Fail closed, but not noisily wrong. A lookalike is not a match: firstmate-notes is not under firstmate, fm-spawn.sh.bak is not fm-spawn.sh, and a MENTION of a pool-leasing script is not an invocation of it - a brief that asks a crewmate to change one of those scripts is ordinary work. Every invocation form must be written as code, because English can put "bash" or a ./ path directly before a script name while saying the opposite of run it; the FM_HOME=$(mktemp -d) half needs no code context and is the truer signal for the third defect anyway. git is the authority for gitignored, so a tracked path a pattern happens to match still reads as visible. The known false-refusal class - a brief that must cite an invisible path - is documented, and FM_PREFLIGHT_OVERRIDE=1 is the loud, logged way through. Gates gate-t1-brief-preflight-rules and gate-t1-brief-preflight-spawn-gate, with a committed fixture per rule plus a clean brief and a lookalike brief that must pass - the two that stop this becoming a gate nothing gets past. Spec: docs/specs/2026-08-31-brief-preflight.md.
This was referenced Sep 2, 2026
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Why
Three briefs written on 2026-08-28/29 specified work no crewmate could do. Each would have cost an entire crewmate run; the intake council caught all three, but only after a full cycle of three model lenses.
data/command-center-roadmap.mdintodocs/" —data/is gitignored, so the file is not in a worktree at all, and a gitignored file cannot be deleted by a commit.data/and are invisible to a crewmate.FM_HOME=$(mktemp -d)" —fm-home-seed.shleases from the live treehouse pool regardless ofFM_HOME, so a "test" run silently leaks a durable lease into the captain's pool.A fourth reached a live crewmate: a brief carrying the retired
>>status redirect, whose reports the permission profile silently refused for ten minutes while the pane looked idle.All four are structural — decidable from the brief text, the project's own ignore rules, and a list of known-hazardous commands, with no model in the loop. This is the same move the Quarterdeck already makes with
fm_gates_classify, applied to intake.What
bin/fm-preflight-lib.shclassifies;bin/fm-spawn.shdecides. The preflight runs after the brief-exists check and ahead of the intake council — it needs no model, and the council exempts scouts, which is exactly what defect 3 was. Nothing is created before a refusal: no pane, no worktree, no meta. Secondmates are exempt (their home is a firstmate home, wheredata/andstate/are theirs to operate).gitignoredprimary-checkoutpool-leasefm-home-seed.sh/fm-spawn.shlease from the live pool whateverFM_HOMEsays, andFM_HOME=$(mktemp -d)claims an isolation it cannot providestatus-redirectbin/fm-status.shThe refusal names the offender. One that only said "invalid brief" would cost another cycle to diagnose, which is half of what this saves:
Fail closed, not noisily wrong
False refusals would train everyone to reach for the override, and then the gate protects nothing. So:
/Users/x/firstmate-notes/ais not under/Users/x/firstmate— the character after the root must be a separator.fm-spawn.sh.bakandmy-fm-spawn.share notfm-spawn.sh.bin/fm-spawn.sh" is ordinary firstmate-on-itself work. Every invocation form must be written as code, because English can put "bash" or a./path directly before a script name while saying the opposite of run it — that class was found by review and is now a fixture.git check-ignoreis the authority forgitignored, without--no-index, so a tracked path some pattern matches still reads as visible.node_modules/— is documented in the spec, andFM_PREFLIGHT_OVERRIDE=1is the loud, logged way through.Gates
gate-t1-brief-preflight-rules— one committed fixture per rule, refused with the offender named;clean.mdandlookalike.mdmust pass, as must the real ship and scout scaffoldsbin/fm-brief.shwrites. Those are what stop this becoming a gate nothing gets past.gate-t1-brief-preflight-spawn-gate—fm-spawnrefuses before anything is created, ahead of the wardroom, for ship and scout alike; clean work gets through; the override is loud; secondmates are exempt.Both born red and proven so (
first_observed_redstamped by aledger verifyagainst a neutered classifier), and both areLEDGER_MUTATE-sensitive.Verification
tests/run-all.sh— 64 ran, 2 skipped, 1 failed. The one failure isfm-herdr-h5-live, a LIVE gate that needs a reachable herdr server; it fails identically on the untouched tree in this environment and this diff touches nothing in the herdr path.gates/verify.sh—green:40 red:3. Two are the declared reds (gate-l2-loop-audit-level,m1-hook-registered); the third is the samegate-h5-herdr-live-roundtrip, which is recorded green in the ledger and goes red only in this environment.bash bin/fm-gates-lib.sh .—OK, every gate acceptable.shellcheck bin/*.sh tests/*.sh— clean.Not in scope
bin/fm-intake.shis not hooked (it would save the council's model calls, but changes the council's contract), and a promoted scout still bypasses this the same way it already bypasses the wardroom. Both are noted in the spec.